home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 10 / AACD 10.iso / AACD / Games / MAME / src / cpu / m6502 / m6502.c < prev    next >
C/C++ Source or Header  |  2000-05-18  |  26KB  |  856 lines

  1. /*****************************************************************************
  2.  *
  3.  *     m6502.c
  4.  *     Portable 6502/65c02/65sc02/6510/n2a03 emulator V1.2
  5.  *
  6.  *     Copyright (c) 1998,1999,2000 Juergen Buchmueller, all rights reserved.
  7.  *     65sc02 core Copyright (c) 2000 Peter Trauner.
  8.  *
  9.  *     - This source code is released as freeware for non-commercial purposes.
  10.  *     - You are free to use and redistribute this code in modified or
  11.  *       unmodified form, provided you list me in the credits.
  12.  *     - If you modify this source code, you must add a notice to each modified
  13.  *       source file that it has been changed.  If you're a nice person, you
  14.  *       will clearly mark each change too.  :)
  15.  *     - If you wish to use this for commercial purposes, please contact me at
  16.  *       pullmoll@t-online.de
  17.  *     - The author of this copywritten work reserves the right to change the
  18.  *       terms of its usage and license at any time, including retroactively
  19.  *     - This entire notice must remain in the source code.
  20.  *
  21.  *****************************************************************************/
  22. /* 2.February 2000 PeT added 65sc02 subtype */
  23. /* 10.March   2000 PeT added 6502 set overflow input line */
  24.  
  25. #include <stdio.h>
  26. #include "driver.h"
  27. #include "state.h"
  28. #include "mamedbg.h"
  29. #include "m6502.h"
  30. #include "ops02.h"
  31. #include "ill02.h"
  32.  
  33.  
  34. #define VERBOSE 0
  35.  
  36. #if VERBOSE
  37. #define LOG(x)    logerror x
  38. #else
  39. #define LOG(x)
  40. #endif
  41.  
  42. /* Layout of the registers in the debugger */
  43. static UINT8 m6502_reg_layout[] = {
  44.     M6502_PC, M6502_S, M6502_P, M6502_A, M6502_X, M6502_Y, -1,
  45.     M6502_EA, M6502_ZP, M6502_NMI_STATE, M6502_IRQ_STATE, M6502_SO_STATE, 0
  46. };
  47.  
  48. /* Layout of the debugger windows x,y,w,h */
  49. static UINT8 m6502_win_layout[] = {
  50.     25, 0,55, 2,    /* register window (top, right rows) */
  51.      0, 0,24,22,    /* disassembler window (left colums) */
  52.     25, 3,55, 9,    /* memory #1 window (right, upper middle) */
  53.     25,13,55, 9,    /* memory #2 window (right, lower middle) */
  54.      0,23,80, 1,    /* command line window (bottom rows) */
  55. };
  56.  
  57. /****************************************************************************
  58.  * The 6502 registers.
  59.  ****************************************************************************/
  60. typedef struct
  61. {
  62.     UINT8    subtype;        /* currently selected cpu sub type */
  63.     void    (**insn)(void); /* pointer to the function pointer table */
  64.     PAIR    ppc;            /* previous program counter */
  65.     PAIR    pc;             /* program counter */
  66.     PAIR    sp;             /* stack pointer (always 100 - 1FF) */
  67.     PAIR    zp;             /* zero page address */
  68.     PAIR    ea;             /* effective address */
  69.     UINT8    a;                /* Accumulator */
  70.     UINT8    x;                /* X index register */
  71.     UINT8    y;                /* Y index register */
  72.     UINT8    p;                /* Processor status */
  73.     UINT8    pending_irq;    /* nonzero if an IRQ is pending */
  74.     UINT8    after_cli;        /* pending IRQ and last insn cleared I */
  75.     UINT8    nmi_state;
  76.     UINT8    irq_state;
  77.     UINT8   so_state;
  78.     int     (*irq_callback)(int irqline);    /* IRQ callback */
  79. }    m6502_Regs;
  80.  
  81. int m6502_ICount = 0;
  82.  
  83. static m6502_Regs m6502;
  84.  
  85. /***************************************************************
  86.  * include the opcode macros, functions and tables
  87.  ***************************************************************/
  88. #include "t6502.c"
  89.  
  90. #if (HAS_M6510)
  91. #include "t6510.c"
  92. #endif
  93.  
  94. #include "opsc02.h"
  95.  
  96. #if (HAS_M65C02)
  97. #include "t65c02.c"
  98. #endif
  99.  
  100. #if (HAS_M65SC02)
  101. #include "t65sc02.c"
  102. #endif
  103.  
  104. #if (HAS_N2A03)
  105. #include "tn2a03.c"
  106. #endif
  107.  
  108. /*****************************************************************************
  109.  *
  110.  *        6502 CPU interface functions
  111.  *
  112.  *****************************************************************************/
  113.  
  114. void m6502_reset(void *param)
  115. {
  116.     m6502.subtype = SUBTYPE_6502;
  117.     m6502.insn = insn6502;
  118.  
  119.     /* wipe out the rest of the m6502 structure */
  120.     /* read the reset vector into PC */
  121.     PCL = RDMEM(M6502_RST_VEC);
  122.     PCH = RDMEM(M6502_RST_VEC+1);
  123.  
  124.     m6502.sp.d = 0x01ff;    /* stack pointer starts at page 1 offset FF */
  125.     m6502.p = F_T|F_I|F_Z|F_B|(P&F_D);    /* set T, I and Z flags */
  126.     m6502.pending_irq = 0;    /* nonzero if an IRQ is pending */
  127.     m6502.after_cli = 0;    /* pending IRQ and last insn cleared I */
  128.     m6502.irq_callback = NULL;
  129.  
  130.     change_pc16(PCD);
  131. }
  132.  
  133. void m6502_exit(void)
  134. {
  135.     /* nothing to do yet */
  136. }
  137.  
  138. unsigned m6502_get_context (void *dst)
  139. {
  140.     if( dst )
  141.         *(m6502_Regs*)dst = m6502;
  142.     return sizeof(m6502_Regs);
  143. }
  144.  
  145. void m6502_set_context (void *src)
  146. {
  147.     if( src )
  148.     {
  149.         m6502 = *(m6502_Regs*)src;
  150.         change_pc(PCD);
  151.     }
  152. }
  153.  
  154. unsigned m6502_get_pc (void)
  155. {
  156.     return PCD;
  157. }
  158.  
  159. void m6502_set_pc (unsigned val)
  160. {
  161.     PCW = val;
  162.     change_pc(PCD);
  163. }
  164.  
  165. unsigned m6502_get_sp (void)
  166. {
  167.     return S;
  168. }
  169.  
  170. void m6502_set_sp (unsigned val)
  171. {
  172.     S = val;
  173. }
  174.  
  175. unsigned m6502_get_reg (int regnum)
  176. {
  177.     switch( regnum )
  178.     {
  179.         case M6502_PC: return m6502.pc.w.l;
  180.         case M6502_S: return m6502.sp.b.l;
  181.         case M6502_P: return m6502.p;
  182.         case M6502_A: return m6502.a;
  183.         case M6502_X: return m6502.x;
  184.         case M6502_Y: return m6502.y;
  185.         case M6502_EA: return m6502.ea.w.l;
  186.         case M6502_ZP: return m6502.zp.w.l;
  187.         case M6502_NMI_STATE: return m6502.nmi_state;
  188.         case M6502_IRQ_STATE: return m6502.irq_state;
  189.         case M6502_SO_STATE: return m6502.so_state;
  190.         case M6502_SUBTYPE: return m6502.subtype;
  191.         case REG_PREVIOUSPC: return m6502.ppc.w.l;
  192.         default:
  193.             if( regnum <= REG_SP_CONTENTS )
  194.             {
  195.                 unsigned offset = S + 2 * (REG_SP_CONTENTS - regnum);
  196.                 if( offset < 0x1ff )
  197.                     return RDMEM( offset ) | ( RDMEM( offset + 1 ) << 8 );
  198.             }
  199.     }
  200.     return 0;
  201. }
  202.  
  203. void m6502_set_reg (int regnum, unsigned val)
  204. {
  205.     switch( regnum )
  206.     {
  207.         case M6502_PC: m6502.pc.w.l = val; break;
  208.         case M6502_S: m6502.sp.b.l = val; break;
  209.         case M6502_P: m6502.p = val; break;
  210.         case M6502_A: m6502.a = val; break;
  211.         case M6502_X: m6502.x = val; break;
  212.         case M6502_Y: m6502.y = val; break;
  213.         case M6502_EA: m6502.ea.w.l = val; break;
  214.         case M6502_ZP: m6502.zp.w.l = val; break;
  215.         case M6502_NMI_STATE: m6502_set_nmi_line( val ); break;
  216.         case M6502_IRQ_STATE: m6502_set_irq_line( 0, val ); break;
  217.         case M6502_SO_STATE: m6502_set_irq_line( M6502_SET_OVERFLOW, val ); break;
  218.         default:
  219.             if( regnum <= REG_SP_CONTENTS )
  220.             {
  221.                 unsigned offset = S + 2 * (REG_SP_CONTENTS - regnum);
  222.                 if( offset < 0x1ff )
  223.                 {
  224.                     WRMEM( offset, val & 0xfff );
  225.                     WRMEM( offset + 1, (val >> 8) & 0xff );
  226.                 }
  227.             }
  228.     }
  229. }
  230.  
  231. INLINE void m6502_take_irq(void)
  232. {
  233.     if( !(P & F_I) )
  234.     {
  235.         EAD = M6502_IRQ_VEC;
  236.         m6502_ICount -= 7;
  237.         PUSH(PCH);
  238.         PUSH(PCL);
  239.         PUSH(P & ~F_B);
  240.         P |= F_I;        /* set I flag */
  241.         PCL = RDMEM(EAD);
  242.         PCH = RDMEM(EAD+1);
  243.         LOG(("M6502#%d takes IRQ ($%04x)\n", cpu_getactivecpu(), PCD));
  244.         /* call back the cpuintrf to let it clear the line */
  245.         if (m6502.irq_callback) (*m6502.irq_callback)(0);
  246.         change_pc16(PCD);
  247.     }
  248.     m6502.pending_irq = 0;
  249. }
  250.  
  251. int m6502_execute(int cycles)
  252. {
  253.     m6502_ICount = cycles;
  254.  
  255.     change_pc16(PCD);
  256.  
  257.     do
  258.     {
  259.         UINT8 op;
  260.         PPC = PCD;
  261.  
  262.         CALL_MAME_DEBUG;
  263.  
  264. #if 1
  265.         /* if an irq is pending, take it now */
  266.         if( m6502.pending_irq )
  267.             m6502_take_irq();
  268.  
  269.         op = RDOP();
  270.         (*m6502.insn[op])();
  271. #else
  272.         /* thought as irq request while executing sei */
  273.         /* sei sets I flag on the stack*/
  274.         op = RDOP();
  275.  
  276.         /* if an irq is pending, take it now */
  277.         if( m6502.pending_irq && (op == 0x78) )
  278.             m6502_take_irq();
  279.  
  280.         (*m6502.insn[op])();
  281. #endif
  282.  
  283.         /* check if the I flag was just reset (interrupts enabled) */
  284.         if( m6502.after_cli )
  285.         {
  286.             LOG(("M6502#%d after_cli was >0", cpu_getactivecpu()));
  287.             m6502.after_cli = 0;
  288.             if (m6502.irq_state != CLEAR_LINE)
  289.             {
  290.                 LOG((": irq line is asserted: set pending IRQ\n"));
  291.                 m6502.pending_irq = 1;
  292.             }
  293.             else
  294.             {
  295.                 LOG((": irq line is clear\n"));
  296.             }
  297.         }
  298.         else
  299.         if( m6502.pending_irq )
  300.             m6502_take_irq();
  301.  
  302.     } while (m6502_ICount > 0);
  303.  
  304.     return cycles - m6502_ICount;
  305. }
  306.  
  307. void m6502_set_nmi_line(int state)
  308. {
  309.     if (m6502.nmi_state == state) return;
  310.     m6502.nmi_state = state;
  311.     if( state != CLEAR_LINE )
  312.     {
  313.         LOG(( "M6502#%d set_nmi_line(ASSERT)\n", cpu_getactivecpu()));
  314.         EAD = M6502_NMI_VEC;
  315.         m6502_ICount -= 7;
  316.         PUSH(PCH);
  317.         PUSH(PCL);
  318.         PUSH(P & ~F_B);
  319.         P |= F_I;        /* set I flag */
  320.         PCL = RDMEM(EAD);
  321.         PCH = RDMEM(EAD+1);
  322.         LOG(("M6502#%d takes NMI ($%04x)\n", cpu_getactivecpu(), PCD));
  323.         change_pc16(PCD);
  324.     }
  325. }
  326.  
  327. void m6502_set_irq_line(int irqline, int state)
  328. {
  329.     if( irqline == M6502_SET_OVERFLOW )
  330.     {
  331.         if( m6502.so_state && !state )
  332.         {
  333.             LOG(( "M6502#%d set overflow\n", cpu_getactivecpu()));
  334.             P|=F_V;
  335.         }
  336.         m6502.so_state=state;
  337.         return;
  338.     }
  339.     m6502.irq_state = state;
  340.     if( state != CLEAR_LINE )
  341.     {
  342.         LOG(( "M6502#%d set_irq_line(ASSERT)\n", cpu_getactivecpu()));
  343.         m6502.pending_irq = 1;
  344.     }
  345. }
  346.  
  347. void m6502_set_irq_callback(int (*callback)(int))
  348. {
  349.     m6502.irq_callback = callback;
  350. }
  351.  
  352. void m6502_state_save(void *file)
  353. {
  354.     int cpu = cpu_getactivecpu();
  355.     state_save_UINT8(file,"m6502",cpu,"TYPE",&m6502.subtype,1);
  356.     /* insn is set at restore since it's a pointer */
  357.     state_save_UINT16(file,"m6502",cpu,"PC",&m6502.pc.w.l,2);
  358.     state_save_UINT16(file,"m6502",cpu,"SP",&m6502.sp.w.l,2);
  359.     state_save_UINT8(file,"m6502",cpu,"P",&m6502.p,1);
  360.     state_save_UINT8(file,"m6502",cpu,"A",&m6502.a,1);
  361.     state_save_UINT8(file,"m6502",cpu,"X",&m6502.x,1);
  362.     state_save_UINT8(file,"m6502",cpu,"Y",&m6502.y,1);
  363.     state_save_UINT8(file,"m6502",cpu,"PENDING",&m6502.pending_irq,1);
  364.     state_save_UINT8(file,"m6502",cpu,"AFTER_CLI",&m6502.after_cli,1);
  365.     state_save_UINT8(file,"m6502",cpu,"NMI_STATE",&m6502.nmi_state,1);
  366.     state_save_UINT8(file,"m6502",cpu,"IRQ_STATE",&m6502.irq_state,1);
  367.     state_save_UINT8(file,"m6502",cpu,"SO_STATE",&m6502.so_state,1);
  368. }
  369.  
  370. void m6502_state_load(void *file)
  371. {
  372.     int cpu = cpu_getactivecpu();
  373.     state_load_UINT8(file,"m6502",cpu,"TYPE",&m6502.subtype,1);
  374.     /* insn is set at restore since it's a pointer */
  375.     switch (m6502.subtype)
  376.     {
  377. #if (HAS_M65C02)
  378.         case SUBTYPE_65C02:
  379.             m6502.insn = insn65c02;
  380.             break;
  381. #endif
  382. #if (HAS_M65SC02)
  383.         case SUBTYPE_65SC02:
  384.             m6502.insn = insn65sc02;
  385.             break;
  386. #endif
  387. #if (HAS_M6510)
  388.         case SUBTYPE_6510:
  389.             m6502.insn = insn6510;
  390.             break;
  391. #endif
  392.         default:
  393.             m6502.insn = insn6502;
  394.             break;
  395.     }
  396.     state_load_UINT16(file,"m6502",cpu,"PC",&m6502.pc.w.l,2);
  397.     state_load_UINT16(file,"m6502",cpu,"SP",&m6502.sp.w.l,2);
  398.     state_load_UINT8(file,"m6502",cpu,"P",&m6502.p,1);
  399.     state_load_UINT8(file,"m6502",cpu,"A",&m6502.a,1);
  400.     state_load_UINT8(file,"m6502",cpu,"X",&m6502.x,1);
  401.     state_load_UINT8(file,"m6502",cpu,"Y",&m6502.y,1);
  402.     state_load_UINT8(file,"m6502",cpu,"PENDING",&m6502.pending_irq,1);
  403.     state_load_UINT8(file,"m6502",cpu,"AFTER_CLI",&m6502.after_cli,1);
  404.     state_load_UINT8(file,"m6502",cpu,"NMI_STATE",&m6502.nmi_state,1);
  405.     state_load_UINT8(file,"m6502",cpu,"IRQ_STATE",&m6502.irq_state,1);
  406.     state_load_UINT8(file,"m6502",cpu,"SO_STATE",&m6502.so_state,1);
  407. }
  408.  
  409. /****************************************************************************
  410.  * Return a formatted string for a register
  411.  ****************************************************************************/
  412. const char *m6502_info(void *context, int regnum)
  413. {
  414.     static char buffer[16][47+1];
  415.     static int which = 0;
  416.     m6502_Regs *r = context;
  417.  
  418.     which = ++which % 16;
  419.     buffer[which][0] = '\0';
  420.     if( !context )
  421.         r = &m6502;
  422.  
  423.     switch( regnum )
  424.     {
  425.         case CPU_INFO_REG+M6502_PC: sprintf(buffer[which], "PC:%04X", r->pc.w.l); break;
  426.         case CPU_INFO_REG+M6502_S: sprintf(buffer[which], "S:%02X", r->sp.b.l); break;
  427.         case CPU_INFO_REG+M6502_P: sprintf(buffer[which], "P:%02X", r->p); break;
  428.         case CPU_INFO_REG+M6502_A: sprintf(buffer[which], "A:%02X", r->a); break;
  429.         case CPU_INFO_REG+M6502_X: sprintf(buffer[which], "X:%02X", r->x); break;
  430.         case CPU_INFO_REG+M6502_Y: sprintf(buffer[which], "Y:%02X", r->y); break;
  431.         case CPU_INFO_REG+M6502_EA: sprintf(buffer[which], "EA:%04X", r->ea.w.l); break;
  432.         case CPU_INFO_REG+M6502_ZP: sprintf(buffer[which], "ZP:%03X", r->zp.w.l); break;
  433.         case CPU_INFO_REG+M6502_NMI_STATE: sprintf(buffer[which], "NMI:%X", r->nmi_state); break;
  434.         case CPU_INFO_REG+M6502_IRQ_STATE: sprintf(buffer[which], "IRQ:%X", r->irq_state); break;
  435.         case CPU_INFO_REG+M6502_SO_STATE: sprintf(buffer[which], "SO:%X", r->so_state); break;
  436.         case CPU_INFO_FLAGS:
  437.             sprintf(buffer[which], "%c%c%c%c%c%c%c%c",
  438.                 r->p & 0x80 ? 'N':'.',
  439.                 r->p & 0x40 ? 'V':'.',
  440.                 r->p & 0x20 ? 'R':'.',
  441.                 r->p & 0x10 ? 'B':'.',
  442.                 r->p & 0x08 ? 'D':'.',
  443.                 r->p & 0x04 ? 'I':'.',
  444.                 r->p & 0x02 ? 'Z':'.',
  445.                 r->p & 0x01 ? 'C':'.');
  446.             break;
  447.         case CPU_INFO_NAME: return "M6502";
  448.         case CPU_INFO_FAMILY: return "Motorola 6502";
  449.         case CPU_INFO_VERSION: return "1.2";
  450.         case CPU_INFO_FILE: return __FILE__;
  451.         case CPU_INFO_CREDITS: return "Copyright (c) 1998 Juergen Buchmueller, all rights reserved.";
  452.         case CPU_INFO_REG_LAYOUT: return (const char*)m6502_reg_layout;
  453.         case CPU_INFO_WIN_LAYOUT: return (const char*)m6502_win_layout;
  454.     }
  455.     return buffer[which];
  456. }
  457.  
  458. unsigned m6502_dasm(char *buffer, unsigned pc)
  459. {
  460. #ifdef MAME_DEBUG
  461.     return Dasm6502( buffer, pc );
  462. #else
  463.     sprintf( buffer, "$%02X", cpu_readop(pc) );
  464.     return 1;
  465. #endif
  466. }
  467.  
  468. /****************************************************************************
  469.  * 65C02 section
  470.  ****************************************************************************/
  471. #if (HAS_M65C02)
  472.  
  473. /* Layout of the registers in the debugger */
  474. static UINT8 m65c02_reg_layout[] = {
  475.     M65C02_A,M65C02_X,M65C02_Y,M65C02_S,M65C02_PC,M65C02_P, -1,
  476.     M65C02_EA,M65C02_ZP,M65C02_NMI_STATE,M65C02_IRQ_STATE, 0
  477. };
  478.  
  479. /* Layout of the debugger windows x,y,w,h */
  480. static UINT8 m65c02_win_layout[] = {
  481.     25, 0,55, 2,    /* register window (top, right rows) */
  482.      0, 0,24,22,    /* disassembler window (left colums) */
  483.     25, 3,55, 9,    /* memory #1 window (right, upper middle) */
  484.     25,13,55, 9,    /* memory #2 window (right, lower middle) */
  485.      0,23,80, 1,    /* command line window (bottom rows) */
  486. };
  487.  
  488.  
  489. void m65c02_reset (void *param)
  490. {
  491.     m6502_reset(param);
  492.     P &=~F_D;
  493.     m6502.subtype = SUBTYPE_65C02;
  494.     m6502.insn = insn65c02;
  495. }
  496.  
  497. void m65c02_exit  (void) { m6502_exit(); }
  498.  
  499. INLINE void m65c02_take_irq(void)
  500. {
  501.     if( !(P & F_I) )
  502.     {
  503.         EAD = M6502_IRQ_VEC;
  504.         m6502_ICount -= 7;
  505.         PUSH(PCH);
  506.         PUSH(PCL);
  507.         PUSH(P & ~F_B);
  508.         P = (P & ~F_D) | F_I;        /* knock out D and set I flag */
  509.         PCL = RDMEM(EAD);
  510.         PCH = RDMEM(EAD+1);
  511.         LOG(("M65c02#%d takes IRQ ($%04x)\n", cpu_getactivecpu(), PCD));
  512.         /* call back the cpuintrf to let it clear the line */
  513.         if (m6502.irq_callback) (*m6502.irq_callback)(0);
  514.         change_pc16(PCD);
  515.     }
  516.     m6502.pending_irq = 0;
  517. }
  518.  
  519. int m65c02_execute(int cycles)
  520. {
  521.     m6502_ICount = cycles;
  522.  
  523.     change_pc16(PCD);
  524.  
  525.     do
  526.     {
  527.         UINT8 op;
  528.         PPC = PCD;
  529.  
  530.         CALL_MAME_DEBUG;
  531.  
  532.         op = RDOP();
  533.         (*m6502.insn[op])();
  534.  
  535.         /* if an irq is pending, take it now */
  536.         if( m6502.pending_irq )
  537.             m65c02_take_irq();
  538.  
  539.  
  540.         /* check if the I flag was just reset (interrupts enabled) */
  541.         if( m6502.after_cli )
  542.         {
  543.             LOG(("M6502#%d after_cli was >0", cpu_getactivecpu()));
  544.             m6502.after_cli = 0;
  545.             if (m6502.irq_state != CLEAR_LINE)
  546.             {
  547.                 LOG((": irq line is asserted: set pending IRQ\n"));
  548.                 m6502.pending_irq = 1;
  549.             }
  550.             else
  551.             {
  552.                 LOG((": irq line is clear\n"));
  553.             }
  554.         }
  555.         else
  556.         if( m6502.pending_irq )
  557.             m65c02_take_irq();
  558.  
  559.     } while (m6502_ICount > 0);
  560.  
  561.     return cycles - m6502_ICount;
  562. }
  563.  
  564. unsigned m65c02_get_context (void *dst) { return m6502_get_context(dst); }
  565. void m65c02_set_context (void *src) { m6502_set_context(src); }
  566. unsigned m65c02_get_pc (void) { return m6502_get_pc(); }
  567. void m65c02_set_pc (unsigned val) { m6502_set_pc(val); }
  568. unsigned m65c02_get_sp (void) { return m6502_get_sp(); }
  569. void m65c02_set_sp (unsigned val) { m6502_set_sp(val); }
  570. unsigned m65c02_get_reg (int regnum) { return m6502_get_reg(regnum); }
  571. void m65c02_set_reg (int regnum, unsigned val) { m6502_set_reg(regnum,val); }
  572.  
  573. void m65c02_set_nmi_line(int state)
  574. {
  575.     if (m6502.nmi_state == state) return;
  576.     m6502.nmi_state = state;
  577.     if( state != CLEAR_LINE )
  578.     {
  579.         LOG(( "M6502#%d set_nmi_line(ASSERT)\n", cpu_getactivecpu()));
  580.         EAD = M6502_NMI_VEC;
  581.         m6502_ICount -= 7;
  582.         PUSH(PCH);
  583.         PUSH(PCL);
  584.         PUSH(P & ~F_B);
  585.         P = (P & ~F_D) | F_I;        /* knock out D and set I flag */
  586.         PCL = RDMEM(EAD);
  587.         PCH = RDMEM(EAD+1);
  588.         LOG(("M6502#%d takes NMI ($%04x)\n", cpu_getactivecpu(), PCD));
  589.         change_pc16(PCD);
  590.     }
  591. }
  592.  
  593. void m65c02_set_irq_line(int irqline, int state) { m6502_set_irq_line(irqline,state); }
  594. void m65c02_set_irq_callback(int (*callback)(int irqline)) { m6502_set_irq_callback(callback); }
  595. void m65c02_state_save(void *file) { m6502_state_save(file); }
  596. void m65c02_state_load(void *file) { m6502_state_load(file); }
  597. const char *m65c02_info(void *context, int regnum)
  598. {
  599.     switch( regnum )
  600.     {
  601.         case CPU_INFO_NAME: return "M65C02";
  602.         case CPU_INFO_VERSION: return "1.2";
  603.         case CPU_INFO_REG_LAYOUT: return (const char*)m65c02_reg_layout;
  604.         case CPU_INFO_WIN_LAYOUT: return (const char*)m65c02_win_layout;
  605.     }
  606.     return m6502_info(context,regnum);
  607. }
  608. unsigned m65c02_dasm(char *buffer, unsigned pc)
  609. {
  610. #ifdef MAME_DEBUG
  611.     return Dasm6502( buffer, pc );
  612. #else
  613.     sprintf( buffer, "$%02X", cpu_readop(pc) );
  614.     return 1;
  615. #endif
  616. }
  617.  
  618. #endif
  619.  
  620. /****************************************************************************
  621.  * 65SC02 section
  622.  ****************************************************************************/
  623. #if (HAS_M65SC02)
  624. /* Layout of the registers in the debugger */
  625. static UINT8 m65sc02_reg_layout[] = {
  626.     M65SC02_A,M65SC02_X,M65SC02_Y,M65SC02_S,M65SC02_PC,M65SC02_P, -1,
  627.     M65SC02_EA,M65SC02_ZP,M65SC02_NMI_STATE,M65SC02_IRQ_STATE, 0
  628. };
  629.  
  630. /* Layout of the debugger windows x,y,w,h */
  631. static UINT8 m65sc02_win_layout[] = {
  632.     25, 0,55, 2,    /* register window (top, right rows) */
  633.      0, 0,24,22,    /* disassembler window (left colums) */
  634.     25, 3,55, 9,    /* memory #1 window (right, upper middle) */
  635.     25,13,55, 9,    /* memory #2 window (right, lower middle) */
  636.      0,23,80, 1,    /* command line window (bottom rows) */
  637. };
  638.  
  639.  
  640. void m65sc02_reset (void *param)
  641. {
  642.     m6502_reset(param);
  643.     m6502.subtype = SUBTYPE_65SC02;
  644.     m6502.insn = insn65sc02;
  645. }
  646. void m65sc02_exit  (void) { m6502_exit(); }
  647. int  m65sc02_execute(int cycles) { return m65c02_execute(cycles); }
  648. unsigned m65sc02_get_context (void *dst) { return m6502_get_context(dst); }
  649. void m65sc02_set_context (void *src) { m6502_set_context(src); }
  650. unsigned m65sc02_get_pc (void) { return m6502_get_pc(); }
  651. void m65sc02_set_pc (unsigned val) { m6502_set_pc(val); }
  652. unsigned m65sc02_get_sp (void) { return m6502_get_sp(); }
  653. void m65sc02_set_sp (unsigned val) { m6502_set_sp(val); }
  654. unsigned m65sc02_get_reg (int regnum) { return m6502_get_reg(regnum); }
  655. void m65sc02_set_reg (int regnum, unsigned val) { m6502_set_reg(regnum,val); }
  656. void m65sc02_set_nmi_line(int state) { m6502_set_nmi_line(state); }
  657. void m65sc02_set_irq_line(int irqline, int state) { m6502_set_irq_line(irqline,state); }
  658. void m65sc02_set_irq_callback(int (*callback)(int irqline)) { m6502_set_irq_callback(callback); }
  659. void m65sc02_state_save(void *file) { m6502_state_save(file); }
  660. void m65sc02_state_load(void *file) { m6502_state_load(file); }
  661. const char *m65sc02_info(void *context, int regnum)
  662. {
  663.     switch( regnum )
  664.     {
  665.         case CPU_INFO_NAME: return "M65SC02";
  666.         case CPU_INFO_FAMILY: return "Metal Oxid Semiconductor MOS 6502";
  667.         case CPU_INFO_VERSION: return "1.0beta";
  668.         case CPU_INFO_CREDITS:
  669.             return "Copyright (c) 1998 Juergen Buchmueller\n"
  670.                 "Copyright (c) 2000 Peter Trauner\n"
  671.                 "all rights reserved.";
  672.         case CPU_INFO_REG_LAYOUT: return (const char*)m65sc02_reg_layout;
  673.         case CPU_INFO_WIN_LAYOUT: return (const char*)m65sc02_win_layout;
  674.     }
  675.     return m6502_info(context,regnum);
  676. }
  677. unsigned m65sc02_dasm(char *buffer, unsigned pc)
  678. {
  679. #ifdef MAME_DEBUG
  680.     return Dasm6502( buffer, pc );
  681. #else
  682.     sprintf( buffer, "$%02X", cpu_readop(pc) );
  683.     return 1;
  684. #endif
  685. }
  686.  
  687. #endif
  688.  
  689. /****************************************************************************
  690.  * 2A03 section
  691.  ****************************************************************************/
  692. #if (HAS_N2A03)
  693. /* Layout of the registers in the debugger */
  694. static UINT8 n2a03_reg_layout[] = {
  695.     N2A03_A,N2A03_X,N2A03_Y,N2A03_S,N2A03_PC,N2A03_P, -1,
  696.     N2A03_EA,N2A03_ZP,N2A03_NMI_STATE,N2A03_IRQ_STATE, 0
  697. };
  698.  
  699. /* Layout of the debugger windows x,y,w,h */
  700. static UINT8 n2a03_win_layout[] = {
  701.     25, 0,55, 2,    /* register window (top, right rows) */
  702.      0, 0,24,22,    /* disassembler window (left colums) */
  703.     25, 3,55, 9,    /* memory #1 window (right, upper middle) */
  704.     25,13,55, 9,    /* memory #2 window (right, lower middle) */
  705.      0,23,80, 1,    /* command line window (bottom rows) */
  706. };
  707.  
  708. void n2a03_reset (void *param)
  709. {
  710.     m6502_reset(param);
  711.     m6502.subtype = SUBTYPE_2A03;
  712.     m6502.insn = insn2a03;
  713. }
  714. void n2a03_exit  (void) { m6502_exit(); }
  715. int  n2a03_execute(int cycles) { return m65c02_execute(cycles); }
  716. unsigned n2a03_get_context (void *dst) { return m6502_get_context(dst); }
  717. void n2a03_set_context (void *src) { m6502_set_context(src); }
  718. unsigned n2a03_get_pc (void) { return m6502_get_pc(); }
  719. void n2a03_set_pc (unsigned val) { m6502_set_pc(val); }
  720. unsigned n2a03_get_sp (void) { return m6502_get_sp(); }
  721. void n2a03_set_sp (unsigned val) { m6502_set_sp(val); }
  722. unsigned n2a03_get_reg (int regnum) { return m6502_get_reg(regnum); }
  723. void n2a03_set_reg (int regnum, unsigned val) { m6502_set_reg(regnum,val); }
  724. void n2a03_set_nmi_line(int state) { m6502_set_nmi_line(state); }
  725. void n2a03_set_irq_line(int irqline, int state) { m6502_set_irq_line(irqline,state); }
  726. void n2a03_set_irq_callback(int (*callback)(int irqline)) { m6502_set_irq_callback(callback); }
  727. void n2a03_state_save(void *file) { m6502_state_save(file); }
  728. void n2a03_state_load(void *file) { m6502_state_load(file); }
  729. const char *n2a03_info(void *context, int regnum)
  730. {
  731.     switch( regnum )
  732.     {
  733.         case CPU_INFO_NAME: return "N2A03";
  734.         case CPU_INFO_VERSION: return "1.0";
  735.         case CPU_INFO_REG_LAYOUT: return (const char*)n2a03_reg_layout;
  736.         case CPU_INFO_WIN_LAYOUT: return (const char*)n2a03_win_layout;
  737.     }
  738.     return m6502_info(context,regnum);
  739. }
  740.  
  741. /* The N2A03 is integrally tied to its PSG (they're on the same die).
  742.    Bit 7 of address $4011 (the PSG's DPCM control register), when set,
  743.    causes an IRQ to be generated.  This function allows the IRQ to be called
  744.    from the PSG core when such an occasion arises. */
  745. void n2a03_irq(void)
  746. {
  747.   m65c02_take_irq();
  748. }
  749.  
  750. unsigned n2a03_dasm(char *buffer, unsigned pc)
  751. {
  752. #ifdef MAME_DEBUG
  753.     return Dasm6502( buffer, pc );
  754. #else
  755.     sprintf( buffer, "$%02X", cpu_readop(pc) );
  756.     return 1;
  757. #endif
  758. }
  759. #endif
  760.  
  761. /****************************************************************************
  762.  * 6510 section
  763.  ****************************************************************************/
  764. #if (HAS_M6510)
  765. /* Layout of the registers in the debugger */
  766. static UINT8 m6510_reg_layout[] = {
  767.     M6510_A,M6510_X,M6510_Y,M6510_S,M6510_PC,M6510_P, -1,
  768.     M6510_EA,M6510_ZP,M6510_NMI_STATE,M6510_IRQ_STATE, 0
  769. };
  770.  
  771. /* Layout of the debugger windows x,y,w,h */
  772. static UINT8 m6510_win_layout[] = {
  773.     25, 0,55, 2,    /* register window (top, right rows) */
  774.      0, 0,24,22,    /* disassembler window (left colums) */
  775.     25, 3,55, 9,    /* memory #1 window (right, upper middle) */
  776.     25,13,55, 9,    /* memory #2 window (right, lower middle) */
  777.      0,23,80, 1,    /* command line window (bottom rows) */
  778. };
  779.  
  780. void m6510_reset (void *param)
  781. {
  782.     m6502_reset(param);
  783.     m6502.subtype = SUBTYPE_6510;
  784.     m6502.insn = insn6510;
  785. }
  786. void m6510_exit  (void) { m6502_exit(); }
  787. int  m6510_execute(int cycles) { return m6502_execute(cycles); }
  788. unsigned m6510_get_context (void *dst) { return m6502_get_context(dst); }
  789. void m6510_set_context (void *src) { m6502_set_context(src); }
  790. unsigned m6510_get_pc (void) { return m6502_get_pc(); }
  791. void m6510_set_pc (unsigned val) { m6502_set_pc(val); }
  792. unsigned m6510_get_sp (void) { return m6502_get_sp(); }
  793. void m6510_set_sp (unsigned val) { m6502_set_sp(val); }
  794. unsigned m6510_get_reg (int regnum) { return m6502_get_reg(regnum); }
  795. void m6510_set_reg (int regnum, unsigned val) { m6502_set_reg(regnum,val); }
  796. void m6510_set_nmi_line(int state) { m6502_set_nmi_line(state); }
  797. void m6510_set_irq_line(int irqline, int state) { m6502_set_irq_line(irqline,state); }
  798. void m6510_set_irq_callback(int (*callback)(int irqline)) { m6502_set_irq_callback(callback); }
  799. void m6510_state_save(void *file) { m6502_state_save(file); }
  800. void m6510_state_load(void *file) { m6502_state_load(file); }
  801. const char *m6510_info(void *context, int regnum)
  802. {
  803.     switch( regnum )
  804.     {
  805.         case CPU_INFO_NAME: return "M6510";
  806.         case CPU_INFO_VERSION: return "1.2";
  807.         case CPU_INFO_REG_LAYOUT: return (const char*)m6510_reg_layout;
  808.         case CPU_INFO_WIN_LAYOUT: return (const char*)m6510_win_layout;
  809.     }
  810.     return m6502_info(context,regnum);
  811. }
  812.  
  813. unsigned m6510_dasm(char *buffer, unsigned pc)
  814. {
  815. #ifdef MAME_DEBUG
  816.     return Dasm6510( buffer, pc );
  817. #else
  818.     sprintf( buffer, "$%02X", cpu_readop(pc) );
  819.     return 1;
  820. #endif
  821. }
  822. #endif
  823.  
  824. #ifdef HAS_M6510T
  825. const char *m6510t_info(void *context, int regnum)
  826. {
  827.     switch( regnum )
  828.     {
  829.         case CPU_INFO_NAME: return "M6510T";
  830.     }
  831.     return m6510_info(context,regnum);
  832. }
  833. #endif
  834.  
  835. #ifdef HAS_M7501
  836. const char *m7501_info(void *context, int regnum)
  837. {
  838.     switch( regnum )
  839.     {
  840.         case CPU_INFO_NAME: return "M7501";
  841.     }
  842.     return m6510_info(context,regnum);
  843. }
  844. #endif
  845.  
  846. #ifdef HAS_M8502
  847. const char *m8502_info(void *context, int regnum)
  848. {
  849.     switch( regnum )
  850.     {
  851.         case CPU_INFO_NAME: return "M8502";
  852.     }
  853.     return m6510_info(context,regnum);
  854. }
  855. #endif
  856.